package buffer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import data.Table.*;
import data.meto.table;
import data.meto.page;
import data.meto.pageMark;


public class pager implements pagerInterface{

	public static String filePath;
	public  List<String> tables ; 
	public  Map<String,table> Alltables;
	public  String  dbName ;
	public  Map<Integer,page> buffers;
	public  Map<Integer,pageMark> buffers_mark;
	public  Map<Integer,page> buffers_freePage;
	public  List<Integer> buffers_freePageList;
	
	
	public  pager(String dbname){
		
		filePath = dbname;
		dbName = dbname;		
		Alltables = getAllTables();
		buffers_freePageList = getFreePageList();
		buffers_freePage = getFreeListPage();
		tables = getTables();	
	}
	
	/**
	 * get all table names from file
	 * @return
	 */
	public List<String> getTables(){
		List<String> tables  =new ArrayList<String>();
		Set<String> tb = Alltables.keySet();
		Iterator<String> it = tb.iterator();
		while(it.hasNext()){
			tables.add(it.next());
		}
		return tables;
	}
	

	
	/**
	 * get all tables from file
	 * @return
	 */
	public Map<String,table> getAllTables(){
		Map<String,table> res = new HashMap<String,table>();
		Table tb = new Table(filePath);
		res = tb.getTables();
		return res;
	}
	
	
	
	/**
	 * use LRU(modified) to eliminate pages 
	 */
	public void eliminate(){

		if(buffers.size() == 0){
			return ;
		}		
		boolean check =false;
		int min = 0|0x80000000+123;
		pageMark tempage = new pageMark();
		Set<Integer> pageint = buffers_mark.keySet();
		Iterator<Integer> it = pageint.iterator();
		while(it.hasNext()){
			Integer tem = it.next();
			
			pageMark patem = buffers_mark.get(tem);
			if(min<patem.getMark()){
				tempage = patem;
				check =true;
			}
		}
		if(check){
			buffers.remove(tempage);
		}		
	}
	
	/**
	 * add new page to the buffers
	 * @param pg
	 */
	public page addNewPage(int pagenum){
		
		page respage = new page(pagenum);
		if(buffers.size()>=bufferSize_default){
			eliminate();
		}	
		pageMark pm = new pageMark();
		pm.setNew();
		pm.setModify(false);
		pm.setPageNum(pagenum);
		buffers.put(pagenum, respage);
		buffers_mark.put(pagenum,pm);
		return respage;
	}
	
	
	/**
	 * target on the page of page number
	 * @param pagenum
	 */
	public void onPage(int pagenum){
		pageMark tempm = new pageMark();
		Set<Integer> se = buffers_mark.keySet();
		Iterator<Integer> it = se.iterator();
		while(it.hasNext()){
			Integer temint = it.next();
			tempm = buffers_mark.get(temint);
			if(temint.intValue() == pagenum){
				tempm.on();
			}else{
				tempm.notOn();
			}
			buffers_mark.put(temint, tempm);
		}
	}
	
	
	/**
	 * get page from buffer,if have no page ,put the page from file to buffer
	 * @param pagenum
	 * @return
	 */
	public page getPage(int pagenum){
		
		boolean check = false;
//		page respage  = new page(pagenum);
		Set<Integer> se = buffers_mark.keySet();
		Iterator<Integer> it = se.iterator();
		while(it.hasNext()){
			Integer tem = it.next();
			if(tem.intValue() == pagenum){
				onPage(pagenum);
				check =true;
//				crespage =  buffers.get(tem);
				return  buffers.get(tem);
			}
		}
		if(!check){
//			respage =  addNewPage(pagenum);
			return  addNewPage(pagenum);
		}
		return null;
	}
	
	
	public Map<Integer,page> getFreeListPage(){
		Map<Integer,page> res = new HashMap<Integer,page>();
		
	    for(int i =0;i<buffers_freePageList.size();i++){
//	    	res.put(ls.get(i), page(i));
	    	
	    	//////get from sun's page method
	    }	
		return res;
	}
	
	public List<Integer> getFreePageList(){
		Table tb = new Table(filePath);
		List<Integer> ls = new ArrayList<Integer>();
		ls = tb.getEmptyPages();
		return ls;
	}
	
	
	
	/**
	 * get new page from the buffer
	 * @return
	 */
	public page getFreePage(){
		int pagenum = 0;
		page respage = new page();
		if(buffers_freePageList.size()>0){			
			pagenum = buffers_freePageList.get(0);
			respage =  buffers_freePage.get(pagenum);
			buffers_freePage.remove(pagenum);
			buffers_freePageList.remove(0);
		}else{
			Table tb = new Table(filePath);
		    pagenum = tb.getEmptyPage();
		    page pg = new page(pagenum);
		    respage = pg;
		}
		buffers.put(pagenum, respage);
		return respage;
	}
	
	
	
	
	
	
}
